﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Index;

namespace Lucandra.Net
{
    internal class LucandraTermVector : TermFreqVector
    {
        private string field;
        private string[] terms;
        private int[] termFreqs;

        public LucandraTermVector(string field, string[] terms, int[] termFreqs)
        {
            this.field = field;
            this.terms = terms;
            this.termFreqs = termFreqs;
        }

        public string GetField()
        {
            return this.field;
        }

        public int Size()
        {
            return this.terms == null ? 0 : this.terms.Length;
        }

        public string[] GetTerms()
        {
            return this.terms;
        }

        public int[] GetTermFrequencies()
        {
            return this.termFreqs;
        }

        public int IndexOf(string termText)
        {
            if (terms == null)
                return -1;
            int res = Array.BinarySearch(this.terms, termText);
            return res >= 0 ? res : -1;
        }

        public int[] IndexesOf(string[] terms, int start, int len)
        {
            int[] res = new int[len];

            for (int i = 0; i < len; i++)
                res[i] = IndexOf(terms[start + i]);
            return res;
        }

        public override string ToString()
        {
            var sb = new StringBuilder();

            sb.AppendFormat("{{0}: ", this.field);
            if (this.terms != null)
            {
                for (int i = 0; i < this.terms.Length; i++)
                {
                    if (i > 0)
                        sb.Append(", ");
                    sb.AppendFormat("{0}/{1}", this.terms[i], this.termFreqs[i]);
                }
            }
            sb.Append('}');

            return sb.ToString();
        }

        public static LucandraTermVector FromLucandraDocument(LucandraDocument doc, string fieldName)
        {
            var indexedTerms = doc.IndexedTerms.Where(t => t.FieldName == fieldName).ToArray();
            int count = indexedTerms.Length;

            string[] terms = new string[count];
            int[] frequencies = new int[count];
            int[][] positions = new int[count][];
            TermVectorOffsetInfo[][] offsets = new TermVectorOffsetInfo[count][];
            bool positionsStored = false;
            bool offsetsStored = false;

            for (int i = 0; i < count; i++)
            {
                var term = indexedTerms[i];

                if (term.StorePositions)
                    positionsStored = true;
                if (term.StoreOffsets)
                    offsetsStored = true;

                terms[i] = term.TermText;
                frequencies[i] = term.Frequency;
                positions[i] = (term.StorePositions ? term.Positions.ToArray() : new int[0]);
                offsets[i] = new TermVectorOffsetInfo[term.OffsetCount / 2];
                var termOffsets = term.Offsets.ToArray();
                for (int x = 0, y = 0; x < termOffsets.Length; x += 2, y++)
                    offsets[i][y] = new TermVectorOffsetInfo(termOffsets[x], termOffsets[x + 1]);
            }

            if (positionsStored || offsetsStored)
                return new LucandraTermPositionVector(fieldName, terms, frequencies, positions, offsets);
            else
                return new LucandraTermVector(fieldName, terms, frequencies);
        }
    }
}
